#ifndef VSNETTASKS_H
#define VSNETTASKS_H

#include <QTcpSocket>
#include "io/vsFileOps.h"

const QString c_single_batch_response = "HTTP/1.1 200 OK";
const QString c_partial_response      = "HTTP/1.1 206 Partial Content";
const QString c_no_content_response   = "HTTP/1.0 204 No Content";
const QString c_robots_go_away        = "User-agent: *\nDisallow: /";
const QString c_cache_control         = "no-cache"; // may be "public; max-age=1800"


namespace vsTypes
{
    typedef enum
    {
        default_header = 0,
        http_get,
        http_head, // metadata request by bots/services
        p2p
    } vsNetHeaderType;
}

struct vsNetHeader
{
    vsTypes::vsNetHeaderType type; // for request

    QString request;
    QString response;

    QString requestURL;     // separated to avoid overwriting by arbitrary parameters
    QString requestBody;    // separated to avoid overwriting by arbitrary parameters

    QStringMap requestParams; // GET /media.vs?key1=value1 <-- those keys + values
    QStringMap headers;

    QStringList dump() const; // write all data into strings

    vsNetHeader() {}
    vsNetHeader(const QStringList &strings);
    vsNetHeader(QTcpSocket *s); /// reads directly from socket

protected:
    void parseRequest();
    void parseHeader(QString header);
};

QTcpSocket& operator<<(QTcpSocket&, const vsNetHeader&);


//----------------------------------------------------------------------

class vsTransferTask : public QObject
{
    Q_OBJECT

public:
    explicit vsTransferTask(QTcpSocket &s, qint64 estimatedByterate, QObject *parent = 0);
    ~vsTransferTask();

    virtual void addDataBlock(const vsDataBlockHolder &b, bool lastOne = false);

    virtual void transfer(qint64 maxBytes);
    virtual void stop();

public slots:
    virtual void onSocketError();

signals:
    void transferComplete(); /// all's done Sir
    void requestMore(); /// reaching end of data blocks when not enough of them to reach total target
    void error(); /// cancelled for some reason, can be deleted

protected:
    QTcpSocket &socket;

    qint64 byterate; /// estimate, used to determine moment to request more data
    qint64 blockReadingPos;
    bool keepWorking;
    bool shouldRequestMore;

    QLinkedList<vsDataBlockHolder> blocks;

    virtual void doneTransferring();
    virtual void mayNeedMore(); /// moving close to end of received data
    virtual void needMore();    /// sent all data, nothing more to send, but not finished yet

private:
    Q_DISABLE_COPY(vsTransferTask)
};


//----------------------------------------------------------------------
/// one time job to send a media file to a peer
class vsFileServeTask : public vsTransferTask
{
    Q_OBJECT

public:
    explicit vsFileServeTask(QTcpSocket &s, const QString &path, qint64 offset, qint64 count, quint64 totalSize,
                             QObject *parent);
    ~vsFileServeTask();

    bool operator==(const vsFileServeTask &other) const;

public slots:
    void onFileRead(int,vsDataBlockHolder dbh);
    void onFileError(int, vsTypes::fileError);

protected:
    void mayNeedMore();
    void needMore();

    void doneTransferring();

    QString fpath;

    qint64 foffset;
    qint64 fcount;
    qint64 fread;
    qint64 fsize;

    QList<QPair<qint64,qint64> > ranges;

    int requested;

    int firstIndex;
    int currentIndex;
    int lastIndex;
};

#endif // VSNETTASKS_H
